package com.feifan.monthhelper.calculate;


import com.blankj.utilcode.util.GsonUtils;
import com.feifan.monthhelper.bean.db.DayRecordBean;
import com.feifan.monthhelper.bean.db.MenstrualRecordBean;
import com.feifan.monthhelper.constant.Constant;
import com.feifan.monthhelper.db.DBUtls;
import com.feifan.monthhelper.utils.DateUtils;
import com.feifan.monthhelper.utils.NumberUtils;
import com.feifan.monthhelper.utils.SPUtils;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cn.qqtheme.framework.util.LogUtils;

/**
 * 月经周期计算类
 */
public class CalculateUtils {

//    public static int MENSTRUAL_DAY = Color.parseColor("#FF66BA");
//    public static int CACULATE_MENSTRUAL_DAY = Color.parseColor("#FD8CCA");
//    public static int SAFE_DAY = Color.parseColor("#77ECB4");
//    public static int OVULATORY_DAY = Color.parseColor("#9DB8EB");
//    static int MENSTRUAL_DAY = 0xFFFF66BA;
//    static int CACULATE_MENSTRUAL_DAY = 0xFFFD8CCA;
//    static int SAFE_DAY = 0xFF77ECB4;
//    static int OVULATORY_DAY = 0xFF9DB8EB;

    /**
     *
     * @param date 当月月经日期
     * @param menstrual_period 月经周期
     * @param span_period 月经间隔周期
     * @return 当月组装后的日期数据
     */
    public static List<com.haibin.calendarview.Calendar> caculateDate(Date date, int menstrual_period, int span_period) {
        List<com.haibin.calendarview.Calendar> calendarBeans = new ArrayList<>();
        Calendar calendar = Calendar.getInstance();
        //清楚缓存，避免影响新设置的值
        calendar.clear();

        calendar.setTime(new Date());
        //今天的日期
        int currentDay = calendar.get(Calendar.DAY_OF_MONTH);

        calendar.setTime(date);
        int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
        int maxDayOfMonth = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
        System.out.println("Calendar.DAY_OF_MONTH ： " + calendar.get(Calendar.DAY_OF_MONTH));

        //计算月经前的日期
        for(int i= 1;i < dayOfMonth;i++) {
            //日历减一天
            calendar.add(Calendar.DATE, -1);
            com.haibin.calendarview.Calendar calendarBean = new com.haibin.calendarview.Calendar();
            calendarBean.setYear(calendar.get(Calendar.YEAR));
            calendarBean.setMonth(calendar.get(Calendar.MONTH) + 1);
            calendarBean.setMonth(calendar.get(Calendar.DAY_OF_MONTH));

            //和经期开始的天数差
            int offset = dayOfMonth -i;
            //排卵前7天安全期
            if(offset < 7) {
                calendarBean.setSchemeColor(Constant.MenstrualColor.SAFE_DAY);
            } else if((offset < 20) && offset > 9) {
                //排卵期--月经来潮前的第14天，为了保险起见把这一天的前5天和后4天连同排卵期在内的共十天称为排卵期
                // 经期开始时间 - 20 < 排卵期 < 经期开始时间 - 9
                calendarBean.setSchemeColor(Constant.MenstrualColor.OVULATORY_DAY);
            }

            //月经期####如果出现本月的上次月经周期，则直接覆盖为月经期
            if(offset > span_period && offset < menstrual_period + span_period) {
                processMenstrualDay(currentDay, i, calendarBean);
            }
            calendarBeans.add(calendarBean);
        }

        //恢复月经期时间
        calendar.setTime(date);
        //月经当天以及之后的日子
        for(int i= dayOfMonth;i <= maxDayOfMonth; i++) {
            //日历减一天
            calendar.add(Calendar.DATE, 1);
            com.haibin.calendarview.Calendar calendarBean = new com.haibin.calendarview.Calendar();
            calendarBean.setYear(calendar.get(Calendar.YEAR));
            calendarBean.setMonth(calendar.get(Calendar.MONTH) + 1);
            calendarBean.setMonth(calendar.get(Calendar.DAY_OF_MONTH));
            //和经期开始的天数差
            int offset = i - dayOfMonth;

            //月经期####
            if(offset < menstrual_period) {
                processMenstrualDay(currentDay, i, calendarBean);
            } else if(offset < menstrual_period + 8) {
                //安全期####月经结束时间后8天
                calendarBean.setSchemeColor(Constant.MenstrualColor.SAFE_DAY);
            }

            //预测经期，一般为下一经期
            if(offset > menstrual_period + span_period) {
                processMenstrualDay(currentDay, i, calendarBean);
            }

            calendarBeans.add(calendarBean);
        }
        System.out.println("Calendar.DAY_OF_MONTH 2222： " + calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
        return calendarBeans;
    }

    private static void processMenstrualDay(int currentDay, int i, com.haibin.calendarview.Calendar calendarBean) {
        //修改算法，计算出来的都是预测经期
        calendarBean.setSchemeColor(Constant.MenstrualColor.CACULATE_MENSTRUAL_DAY);

//        //判断是否为预测经期
//        if (currentDay < i) {
//            //月经期如果还未到，则为预测月经期
//            calendarBean.setSchemeColor(CACULATE_MENSTRUAL_DAY);
//        } else {
//            calendarBean.setSchemeColor(MENSTRUAL_DAY);
//        }
    }

    /**
     *
     * @param date 当月月经日期
     * @param menstrual_period 月经周期
     * @param span_period 月经间隔周期
     * @return 当月组装后的日期数据
     */
    public static Map<String, com.haibin.calendarview.Calendar> caculateDateMap(Date date, int menstrual_period, int span_period) {
        Map<String, com.haibin.calendarview.Calendar> calendarMap = new HashMap<>();
        Calendar calendar = Calendar.getInstance();
        //清楚缓存，避免影响新设置的值
        calendar.clear();

        calendar.setTime(new Date());
        //今天的日期
        int currentDay = calendar.get(Calendar.DAY_OF_MONTH);
        int currentMonth = calendar.get(Calendar.MONTH);

        calendar.setTime(date);
        //计算下一个月经周期，直到为月经在当月
        calendar =caculateNextMenstrual(menstrual_period + span_period, calendar, currentMonth);

        //保存当月经期时间
        Date currentMenstrualDate = calendar.getTime();

        int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
        int maxDayOfMonth = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
        System.out.println("Calendar.DAY_OF_MONTH ： " + calendar.get(Calendar.DAY_OF_MONTH));

        //计算月经前的日期
        for(int i= 1;i < dayOfMonth;i++) {
            //和经期开始的天数差
            int offset = dayOfMonth -i;

            //日历减一天
            calendar.add(Calendar.DATE, -1);
            com.haibin.calendarview.Calendar calendarBean = new com.haibin.calendarview.Calendar();
            calendarBean.setYear(calendar.get(Calendar.YEAR));
            calendarBean.setMonth(calendar.get(Calendar.MONTH) + 1);
            calendarBean.setDay(calendar.get(Calendar.DAY_OF_MONTH));

            //排卵前7天安全期
            if(i < 7) {
                System.out.println("Calendar.DAY_OF_MONTH ： 排卵前7天安全期" );
                calendarBean.setSchemeColor(Constant.MenstrualColor.SAFE_DAY);
                calendarMap.put(calendarBean.toString(), calendarBean);
            } else if((i < 20) && i > 9) {
                //排卵期--月经来潮前的第14天，为了保险起见把这一天的前5天和后4天连同排卵期在内的共十天称为排卵期
                // 经期开始时间 - 20 < 排卵期 < 经期开始时间 - 9
                calendarBean.setSchemeColor(Constant.MenstrualColor.OVULATORY_DAY);
                calendarMap.put(calendarBean.toString(), calendarBean);
                System.out.println("Calendar.DAY_OF_MONTH ： 月经来潮前排卵期" );
            }

            //月经期####如果出现本月的上次月经周期，则直接覆盖为月经期
            if(i > span_period && i < menstrual_period + span_period) {
                menstrualOrCalculate(currentDay, offset, calendarBean);
                calendarMap.put(calendarBean.toString(), calendarBean);
            }
            System.out.println("Calendar.DAY_OF_MONTH ： " + DateUtils.init().dateToString(calendar.getTime(), DateUtils.DateStyle.YYYY_MM_DD));
        }

        //恢复月经期时间
        calendar.setTime(currentMenstrualDate);
        System.out.println("Calendar.DAY_OF_MONTH ： 恢复月经期时间" + DateUtils.init().dateToString(calendar.getTime(), DateUtils.DateStyle.YYYY_MM_DD));

        //月经当天以及之后的日子
        for(int i= dayOfMonth;i <= maxDayOfMonth; i++) {
            com.haibin.calendarview.Calendar calendarBean = new com.haibin.calendarview.Calendar();
            calendarBean.setYear(calendar.get(Calendar.YEAR));
            calendarBean.setMonth(calendar.get(Calendar.MONTH) + 1);
            calendarBean.setDay(calendar.get(Calendar.DAY_OF_MONTH));
            //和经期开始的天数差
            int offset = i - dayOfMonth;

            //月经期####
            if(offset < menstrual_period) {
                menstrualOrCalculate(currentDay, i, calendarBean);
                calendarMap.put(calendarBean.toString(), calendarBean);
            } else if(offset < menstrual_period + 8) {
                //安全期####月经结束时间后8天
                calendarBean.setSchemeColor(Constant.MenstrualColor.SAFE_DAY);
                calendarMap.put(calendarBean.toString(), calendarBean);
                System.out.println("Calendar.DAY_OF_MONTH ： 安全期####月经结束时间后8天" );
            }

            //预测经期，一般为下一经期
            if(offset > menstrual_period + span_period) {
                menstrualOrCalculate(currentDay, i, calendarBean);
                calendarMap.put(calendarBean.toString(), calendarBean);
            }
            System.out.println("Calendar.DAY_OF_MONTH ： " + calendarBean.getYear() + "-" + calendarBean.getMonth() + "-" + calendarBean.getDay());

            //日历减一天
            calendar.add(Calendar.DATE, 1);
        }
        System.out.println("Calendar.DAY_OF_MONTH 2222： " + calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
        return calendarMap;
    }

    /**
     *
     * @param date 当月月经日期
     * @param menstrual_period 月经周期
     * @param span_period 月经间隔周期
     * @return 当月组装后的日期数据
     */
    public static List<DayRecordBean> calculateAndInsertToDb(Date date, int menstrual_period, int span_period) {
        return calculateAndInsertToDb(date, menstrual_period, span_period, null);
    }

    /**
     *
     * @param date 当月月经日期
     * @param menstrual_period 月经周期
     * @param span_period 月经间隔周期
     * @param calculateStartDate 开始计算的日期
     * @return 当月组装后的日期数据
     */
    public static List<DayRecordBean> calculateAndInsertToDb(Date date, int menstrual_period, int span_period, Date calculateStartDate) {
        //获取计算环境封装类
        CalculateContext calculateContext = new CalculateContext(date, menstrual_period, span_period);

        List<DayRecordBean> dayRecordBeans = new ArrayList<>();
        Calendar calendar = Calendar.getInstance();
        //清楚缓存，避免影响新设置的值
        calendar.clear();

        calendar.setTime(new Date());
        // 时
        clearToDayTime(calendar);
        //往后计算两个月
        calendar.add(Calendar.MONTH, 2);
        //setTime之后先get一次，让calendar重新计算一次时间，否则不会计算
        long currentDay = calendar.get(Calendar.DAY_OF_YEAR);
        currentDay = calendar.getTimeInMillis()/Constant.DAY_MILLISSECOND;

        if(calculateStartDate == null) {
            // 如果开始计算日期为null，则从月经记录日期当月1号开始计算
            calendar.setTime(date);
            calendar.set(java.util.Calendar.DAY_OF_MONTH, 1);
        } else {
            calendar.setTime(calculateStartDate);
        }
        //setTime之后先get一次，让calendar重新计算一次时间，否则不会计算
        long dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
        dayOfMonth = calendar.getTimeInMillis()/Constant.DAY_MILLISSECOND;
        if(currentDay > dayOfMonth) {
            //是否需要更新周期开始日期
            boolean updateMenstrualDay = false;
            for(int i=0;i<=currentDay-dayOfMonth;i++ ) {
                DayRecordBean dayRecordBean = new DayRecordBean();
                dayRecordBean.createDate = calendar.getTime();
                dayRecordBean = calculateContext.calculate(dayRecordBean);
                dayRecordBeans.add(dayRecordBean);
                LogUtils.debug(DateUtils.init().longToTime(dayRecordBean.createDate.getTime(), DateUtils.DateStyle.YYYY_MM_DD));

                //如果时预测周期开始时间，则更新算法封装类的周期开始时间
                if(updateMenstrualDay && dayRecordBean.state == Constant.MenstrualState.CACULATE_MENSTRUAL_DAY) {
                    calculateContext.setDate(dayRecordBean.createDate);
                    updateMenstrualDay = false;
                } else {
                    updateMenstrualDay = true;
                }
                //日历加一天
                calendar.add(Calendar.DATE, 1);
//                com.blankj.utilcode.util.LogUtils.d(DateUtils.init().dateToString(dayRecordBean.createDate, DateUtils.DateStyle.YYYY_MM_DD));
            }
        }
        DBUtls.insertDayRecords(dayRecordBeans);
        return dayRecordBeans;
    }

//    public static List<DayRecordBean> calculateBetween(Date lastMenstrualDate, Date nextMenstrualDate, int menstrual_period, int span_period, Date calculateStartDate) {
//        List<DayRecordBean> recordBeans = new ArrayList<>();
//        long count = nextMenstrualDate.getTime()/Constant.DAY_MILLISSECOND - lastMenstrualDate.getTime()/Constant.DAY_MILLISSECOND;
//        for() {
//
//        }
//    }

    /**
     * 新周期预测计算 （当周期参数改变时用于计算新的预测数据，不会覆盖原来数据，只做状态更换）
     * @param date 当月月经日期
     * @param menstrual_period 月经周期
     * @param span_period 月经间隔周期
     * @param dayRecordBeans 要更新的数据
     * @return 当月组装后的日期数据
     */
    public static List<DayRecordBean> calculateAndUpdateToDb(Date date, int menstrual_period, int span_period, List<DayRecordBean> dayRecordBeans, List<MenstrualRecordBean> menstrualRecordBeans) {
        //获取计算环境封装类
        CalculateContext calculateContext = new CalculateContext(date, menstrual_period, span_period);

        Calendar calendar = Calendar.getInstance();
        //清楚缓存，避免影响新设置的值
        calendar.clear();

        calendar.setTime(new Date());
        clearToDayTime(calendar);
        //往后计算两个月
        calendar.add(Calendar.MONTH, 2);
        //setTime之后先get一次，让calendar重新计算一次时间，否则不会计算
        long currentDay = calendar.get(Calendar.DAY_OF_YEAR);
        currentDay = calendar.getTimeInMillis()/Constant.DAY_MILLISSECOND;

        // 从月经记录日期当月1号开始计算
        calendar.setTime(date);
        calendar.set(java.util.Calendar.DAY_OF_MONTH, 1);
        //setTime之后先get一次，让calendar重新计算一次时间，否则不会计算
        long dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
        dayOfMonth = calendar.getTimeInMillis()/Constant.DAY_MILLISSECOND;

        if(dayRecordBeans == null) {
            dayRecordBeans = new ArrayList<>();
            //第一次月经记录之前全是安全期
            int preCount = (int) (getDayCount(date) - dayOfMonth);
            for(int i=0;i<preCount;i++) {
                DayRecordBean dayRecordBean = new DayRecordBean();
                dayRecordBean.state = Constant.MenstrualState.SAFE_DAY;
                dayRecordBean.createDate = addDate(date, i - preCount);
                dayRecordBeans.add(dayRecordBean);
            }
        } else {
            //计算原始数据
            calculateOldData(dayRecordBeans, calculateContext, menstrualRecordBeans, span_period, menstrual_period);
        }

        long calculateCount = currentDay - dayOfMonth - dayRecordBeans.size();

        calculateFromMenstrualDate(date, menstrual_period, span_period, dayRecordBeans, calculateContext, calculateCount);

//        //最近的一次月经周期
//        Date lastDate = date;
//        if(menstrualRecordBeans != null) {
//            //降序排序
//            Collections.sort(menstrualRecordBeans);
//            lastDate = menstrualRecordBeans.get(0).start_date;
//        }
//        calculateContext.setDate(lastDate);
//
////        long calculateCount = currentDay - dayOfMonth - dayRecordBeans.size();
//        long calculateCount = currentDay - dayOfMonth - getDayCount(lastDate);
//        dayOfMonth += dayRecordBeans.size();
//        calendar.add(Calendar.DATE, dayRecordBeans.size());
//        if(calculateCount > 0) {
//            //是否需要更新周期开始日期
//            boolean updateMenstrualDay = false;
//            for(int i=0;i<=calculateCount;i++ ) {
//                DayRecordBean dayRecordBean = new DayRecordBean();
//                dayRecordBean.createDate = calendar.getTime();
//                dayRecordBean = calculateContext.calculate(dayRecordBean);
//                dayRecordBeans.add(dayRecordBean);
//                LogUtils.debug(DateUtils.init().longToTime(dayRecordBean.createDate.getTime(), DateUtils.DateStyle.YYYY_MM_DD));
//
//                //如果时预测周期开始时间，则更新算法封装类的周期开始时间
//                if((i + 1)%span_period == 0) {
//                    calculateContext.setDate(dayRecordBean.createDate);
//                }
//                System.out.println("daybean = " + GsonUtils.toJson(dayRecordBean));
//                //日历加一天
//                calendar.add(Calendar.DATE, 1);
//            }
//        }

        DBUtls.insertDayRecords(dayRecordBeans);
        return dayRecordBeans;
    }

    /**
     * 从指定日期开始添加周期（第一次初始化时使用）
     * @param date
     * @param menstrual_period
     * @param span_period
     * @param dayRecordBeans
     * @param calculateContext
     * @param calculateCount
     */
    public static void calculateFromMenstrualDate(Date date, int menstrual_period, int span_period, List<DayRecordBean> dayRecordBeans, CalculateContext calculateContext, long calculateCount) {
        Date preDate = date;
        Date calculateDate = addDate(preDate, span_period);
        int size = span_period;
        calculateContext.setDate(calculateDate);
        for(int i=0;i<calculateCount;) {

            size = getDateSpan(calculateDate, preDate);
            int menstrualCount = size <= menstrual_period ? size : menstrual_period;
            for(int k=0;k<menstrualCount;k++) {
                DayRecordBean dayRecordBean = new DayRecordBean();
                dayRecordBean.createDate = addDate(preDate, k + 1);
                //预测安全期
                dayRecordBean.state = Constant.MenstrualState.CACULATE_MENSTRUAL_DAY;
                dayRecordBeans.add(dayRecordBean);
            }

            if(size > menstrual_period) {
                for(int k=menstrual_period;k<size;k++) {
                    DayRecordBean dayRecordBean = new DayRecordBean();
                    dayRecordBean.createDate = addDate(preDate, k + 1);
                    if(dayRecordBean.state != Constant.MenstrualState.MENSTRUAL_DAY) {
                        dayRecordBean = calculateContext.calculate(dayRecordBean);
                        System.out.println("dayRecordBeans add= " + GsonUtils.toJson(dayRecordBean));
                    }
                    dayRecordBeans.add(dayRecordBean);
                }
            }
            i += size;

            preDate = calculateDate;
            calculateDate = addDate(calculateDate, span_period);
            calculateContext.setDate(calculateDate);

        }
    }

    /**
     * 从指定日期开始计算周期（选择周期开始后调用）
     * @param date 开始计算的周期开始日期
     * @param current_period 当前经期时长，即date开始的经期时长
     * @param menstrual_period
     * @param span_period
     * @param dayRecordBeans
     */
    public static List<DayRecordBean> calculateFromAfterMenstrualDate(Date date, int current_period, int menstrual_period, int span_period, List<DayRecordBean> dayRecordBeans) {
        //获取计算环境封装类
        CalculateContext calculateContext = new CalculateContext(date, menstrual_period, span_period);

        //往后多计算60天
        int calculateCount = dayRecordBeans.size() > 60 ? dayRecordBeans.size() : 60;

        Date preDate = date;
        Date calculateDate = addDate(date, span_period);
        int size = span_period;
        //标准往周期前计算大小
        int calculateSize = span_period - menstrual_period;
        //计算偏移量，即计算是从上次月经结束开始到下次月经开始，偏移量极为上次月经的经期
        int offset = current_period;
        calculateContext.setDate(calculateDate);
        for(int i=0;i<calculateCount;) {

            size = getDateSpan(calculateDate, preDate);
            if(size > offset) {

                for(int k=offset;k<size + span_period;k++) {
                    int index = k + i;
                    DayRecordBean dayRecordBean;
                    if(dayRecordBeans.size() <= index) {
                        dayRecordBean = new DayRecordBean();
                        dayRecordBean.createDate = addDate(preDate, k + 1);
                        dayRecordBeans.add(dayRecordBean);
                    } else {
                        dayRecordBean = dayRecordBeans.get(index);
                    }
                    if(dayRecordBean.state != Constant.MenstrualState.MENSTRUAL_DAY) {
                        dayRecordBean = calculateContext.calculate(dayRecordBean);
                        System.out.println("dayRecordBeans add= " + GsonUtils.toJson(dayRecordBean));
                    }
                }
            }
//            int menstrualCount = size <= calculateSize ? size : calculateSize;
//            for(int k=0;k<menstrualCount;k++) {
//                int index = k + i;
//                DayRecordBean dayRecordBean;
//                if(dayRecordBeans.size() <= index) {
//                    dayRecordBean = new DayRecordBean();
//                    dayRecordBean.createDate = addDate(preDate, k + 1);
//                    dayRecordBeans.add(dayRecordBean);
//                } else {
//                    dayRecordBean = dayRecordBeans.get(index);
//                }
//                if(dayRecordBean.state != Constant.MenstrualState.MENSTRUAL_DAY) {
////                    dayRecordBean = calculateContext.calculate(dayRecordBean);
//                    dayRecordBean.state = Constant.MenstrualState.CACULATE_MENSTRUAL_DAY;
//                    System.out.println("dayRecordBeans add= " + GsonUtils.toJson(dayRecordBean));
//                }
//            }


            i += size;
            //回复正常偏移量
            offset = menstrual_period;

            preDate = calculateDate;
            calculateDate = addDate(calculateDate, span_period);
            calculateContext.setDate(calculateDate);

        }
        return dayRecordBeans;
    }

    public static List<DayRecordBean> calculateFrombeforeMenstrualDate(Date preDate, Date calculateDate, int menstrual_period, int span_period, List<DayRecordBean> dayRecordBeans) {
        //获取计算环境封装类
        CalculateContext calculateContext = new CalculateContext(calculateDate, menstrual_period, span_period);

        //往后多计算60天
        int calculateCount = dayRecordBeans.size();

        int offset = getDateSpan(calculateDate, preDate);
        int size = offset > calculateCount ? calculateCount : offset;
        calculateContext.setDate(calculateDate);
//        for(int i=0;i<calculateCount;) {

//            size = getDateSpan(calculateDate, preDate);
//            int menstrualCount = size <= menstrual_period ? size : menstrual_period;
//            for(int k=0;k<menstrualCount;k++) {
//                int index = k + i;
//                DayRecordBean dayRecordBean;
//                if(dayRecordBeans.size() <= index) {
//                    dayRecordBean = new DayRecordBean();
//                    dayRecordBean.createDate = addDate(preDate, k + 1);
//                    dayRecordBeans.add(dayRecordBean);
//                } else {
//                    dayRecordBean = dayRecordBeans.get(index);
//                }
//                if(dayRecordBean.state != Constant.MenstrualState.MENSTRUAL_DAY) {
//                    dayRecordBean = calculateContext.calculate(dayRecordBean);
//                    System.out.println("dayRecordBeans add= " + GsonUtils.toJson(dayRecordBean));
//                }
//            }


            for(int k=calculateCount - 1;k>=calculateCount - size;k--) {
                DayRecordBean dayRecordBean;
                dayRecordBean = dayRecordBeans.get(k);
                if(dayRecordBean.state != Constant.MenstrualState.MENSTRUAL_DAY) {
                    dayRecordBean = calculateContext.calculate(dayRecordBean);
                    System.out.println("dayRecordBeans add= " + GsonUtils.toJson(dayRecordBean));
                }
//                if(dayRecordBeans.size() <= index) {
//                    dayRecordBean = new DayRecordBean();
//                    dayRecordBean.createDate = addDate(preDate, k + 1);
//                    dayRecordBeans.add(dayRecordBean);
//                } else {
//                }
            }
//            i += size;
//
//            preDate = calculateDate;
//            calculateDate = addDate(calculateDate, span_period);
//            calculateContext.setDate(calculateDate);
//
//        }
        return dayRecordBeans;
    }

    /**
     * 清除日历对象的时分秒，毫秒
     * @param calendar 日历对象
     */
    private static void clearToDayTime(Calendar calendar) {
        // 时
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        // 分
        calendar.set(Calendar.MINUTE, 0);
        // 秒
        calendar.set(Calendar.SECOND, 0);
        // 毫秒
        calendar.set(Calendar.MILLISECOND, 0);
    }

    /**
     * 计算原来已存在的数据项
     * @param dayRecordBeans 要计算的原始数据
     * @param calculateContext 计算算法
     */
    private static void calculateOldData(List<DayRecordBean> dayRecordBeans, CalculateContext calculateContext, List<MenstrualRecordBean> menstrualRecordBeans, int span_period, int menstrual_period) {

//        //升序过来
//        Collections.reverse(menstrualRecordBeans);
        Collections.sort(dayRecordBeans);
        //上一周期开始时间
        Date lastDate = null;
        if((menstrualRecordBeans != null && menstrualRecordBeans.size() > 0) && (dayRecordBeans != null && !dayRecordBeans.isEmpty())) {
            lastDate = menstrualRecordBeans.get(0).start_date;
            long firstDayRecord = getDayCount(dayRecordBeans.get(0).createDate);
            long lastDayRecord = getDayCount(dayRecordBeans.get(dayRecordBeans.size() -1).createDate);
            for(int i=0;i<menstrualRecordBeans.size();i++) {
                MenstrualRecordBean recordBean = menstrualRecordBeans.get(i);
                //最后一条数据
                if(i == menstrualRecordBeans.size() -1) {
                    long mestraulDay = getDayCount(recordBean.start_date);
                    long offset = mestraulDay - firstDayRecord;
                    if(mestraulDay > firstDayRecord && mestraulDay < lastDayRecord) {
                        calculateContext.setDate(recordBean.start_date);
                        calculateDate(dayRecordBeans, calculateContext, recordBean.start_date, offset);
//                        for(int j=0;j<offset;j++) {
//                            DayRecordBean dayRecordBean = dayRecordBeans.get(j);
//                            if(dayRecordBean.state != Constant.MenstrualState.MENSTRUAL_DAY) {
//                                dayRecordBean = calculateContext.calculate(dayRecordBean);
//                                System.out.println("dayRecordBeans = " + GsonUtils.toJson(dayRecordBean));
//                            }
//                        }
                    }
                } else {
                    long preMenstrualDay = getDayCount(menstrualRecordBeans.get(i+1).start_date);
                    long mestraulDay = getDayCount(recordBean.start_date);
                    long offset = mestraulDay - preMenstrualDay;
                    if(mestraulDay > firstDayRecord && mestraulDay < lastDayRecord) {
                        calculateDate(dayRecordBeans, calculateContext, recordBean.start_date, offset);
                    }
                }
            }
            lastDate = menstrualRecordBeans.get(0).end_date;
            if(lastDayRecord > getDayCount(lastDate)) {

                Date preDate = menstrualRecordBeans.get(0).start_date;
                Date calculateDate = addDate(preDate, span_period);
                long calculateCount = lastDayRecord - getDayCount(preDate);
                int size = span_period;
                calculateContext.setDate(calculateDate);
                for(int i=0;i<calculateCount;i = i+size ) {

                    if(calculateCount -i  < size) {
                        size = (int) (calculateCount -i);
                    }
                    for(int j=0;j<size;j++) {
                        int index = (int) (j+ getDayCount(preDate) - firstDayRecord) + menstrual_period;
                        System.out.println("index = " + index);
                        DayRecordBean dayRecordBean;
                        if(index >= dayRecordBeans.size()) {
                            dayRecordBean = new DayRecordBean();
                            dayRecordBean.createDate = addDate(dayRecordBeans.get(index -1).createDate, 1);
                            if(dayRecordBean.state != Constant.MenstrualState.MENSTRUAL_DAY) {
                                dayRecordBean = calculateContext.calculate(dayRecordBean);
                                System.out.println("dayRecordBeans add= " + GsonUtils.toJson(dayRecordBean));
                            }
                            dayRecordBeans.add(dayRecordBean);
                        } else {
                            dayRecordBean = dayRecordBeans.get(index);
                            if(dayRecordBean.state != Constant.MenstrualState.MENSTRUAL_DAY) {
                                dayRecordBean = calculateContext.calculate(dayRecordBean);
                                System.out.println("dayRecordBeans up = " + GsonUtils.toJson(dayRecordBean));
                            }
                        }
                        System.out.println("dayRecordBeans = " + GsonUtils.toJson(dayRecordBean));
                    }

                    preDate = calculateDate;
                    calculateDate = addDate(calculateDate, span_period);
                    calculateContext.setDate(calculateDate);

                }
            }
        }
    }

    private static void calculateDate(List<DayRecordBean> dayRecordBeans, CalculateContext calculateContext, Date menstrualDate, long offset) {
        calculateContext.setDate(menstrualDate);
        for(int j=0;j<offset;j++) {
            DayRecordBean dayRecordBean = dayRecordBeans.get(j);
            if(dayRecordBean.state != Constant.MenstrualState.MENSTRUAL_DAY) {
                dayRecordBean = calculateContext.calculate(dayRecordBean);
//                System.out.println("dayRecordBeans = " + GsonUtils.toJson(dayRecordBean));
            }
//            System.out.println("dayRecordBeans = " + GsonUtils.toJson(dayRecordBean));
        }
    }

    public static List<DayRecordBean> calculateAndSaveToDb() {
//        return calculateAndSaveToDb(null);
        return calculateAndUpdateToDb(null, null);
    }

    public static List<DayRecordBean> calculateAndSaveToDb(Date calculateStartDate) {
        String menstrual = SPUtils.getInstance().getString(Constant.ShareKey.MENSTRUAL_CYCLE_START_DATE);
        String menstrual_cycle = SPUtils.getInstance().getString(Constant.ShareKey.MENSTRUAL_CYCLE_DAYS);
        String menstrual_span = SPUtils.getInstance().getString(Constant.ShareKey.MENSTRUAL_CYCLE_SPAN_DAYS);
        int menstrual_period = NumberUtils.StringToInt(menstrual_cycle.replaceAll("天", ""));
        int span_period = NumberUtils.StringToInt(menstrual_span.replaceAll("天", ""));
        return CalculateUtils.calculateAndInsertToDb(DateUtils.init().StringToDate(menstrual, DateUtils.DateStyle.YYYY_MM_DD), menstrual_period, span_period, calculateStartDate);
    }

    public static List<DayRecordBean> calculateAndUpdateToDb(List<DayRecordBean> dayRecordBeans, List<MenstrualRecordBean> menstrualRecordBeans) {
        String menstrual = SPUtils.getInstance().getString(Constant.ShareKey.MENSTRUAL_CYCLE_START_DATE);
        String menstrual_cycle = SPUtils.getInstance().getString(Constant.ShareKey.MENSTRUAL_CYCLE_DAYS);
        String menstrual_span = SPUtils.getInstance().getString(Constant.ShareKey.MENSTRUAL_CYCLE_SPAN_DAYS);
        int menstrual_period = NumberUtils.StringToInt(menstrual_cycle.replaceAll("天", ""));
        int span_period = NumberUtils.StringToInt(menstrual_span.replaceAll("天", ""));
        return CalculateUtils.calculateAndUpdateToDb(DateUtils.init().StringToDate(menstrual, DateUtils.DateStyle.YYYY_MM_DD), menstrual_period, span_period, dayRecordBeans, menstrualRecordBeans);
    }

    /**
     * 计算指定日期的预测月经状态
     * @param date 当月月经日期
     * @param menstrual_period 月经周期
     * @param span_period 月经间隔周期
     * @param dayRecordBean 要计算的日期
     * @return 当月组装后的日期数据
     */
    public static DayRecordBean caculateDayRecordBean(Date date, int menstrual_period, int span_period, DayRecordBean dayRecordBean) {
        //获取计算环境封装类
        CalculateContext calculateContext = new CalculateContext(date, menstrual_period, span_period);

        dayRecordBean = calculateContext.calculate(dayRecordBean);
        return dayRecordBean;
    }

    /**
     * 计算指定日期偏移天数的气体
     * @param date
     * @param menstrual_period
     * @param span_period
     * @param calculateDate
     * @return
     */
    public static Date caculateOffsetDate(Date date, int menstrual_period, int span_period, Date calculateDate, int offsetDays) {
        //获取计算环境封装类
        CalculateContext calculateContext = new CalculateContext(date, menstrual_period, span_period);

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(calculateDate);
        calendar.add(Calendar.MONTH, offsetDays);
        return calculateDate;
    }

    /**
     * 月经期或预测月经期处理
     * @param currentDayOfMonth 今天是当月的第几天
     * @param calculateDayOfMonth 要判断的是当月的第几天
     * @param calendarBean 要处理的日期标记数据，用于设置颜色
     */
    private static void menstrualOrCalculate(int currentDayOfMonth, int calculateDayOfMonth, com.haibin.calendarview.Calendar calendarBean) {
        if (currentDayOfMonth < calculateDayOfMonth) {
            //月经期如果还未到，则为预测月经期
            calendarBean.setSchemeColor(Constant.MenstrualColor.CACULATE_MENSTRUAL_DAY);
            System.out.println("Calendar.DAY_OF_MONTH ： 预测月经期");
        } else {
            calendarBean.setSchemeColor(Constant.MenstrualColor.MENSTRUAL_DAY);
            System.out.println("Calendar.DAY_OF_MONTH ： 月经期");
        }
    }

    //计算下一个月经周期，递归到当月时间
    private static Calendar caculateNextMenstrual(int menstrual_cycle, Calendar calendar, int currentMonth) {
        int menstrualMonth = calendar.get(Calendar.MONTH);
        if(menstrualMonth < currentMonth) {
            calendar.add(Calendar.DATE, menstrual_cycle);
            return caculateNextMenstrual(menstrual_cycle, calendar, currentMonth);
        } else {
            return calendar;
        }
    }

    public static int getDateSpan(Date startDate, Date endDate) {
        return (int) (getDayCount(startDate) - getDayCount(endDate));
    }

    //date转到1790天数
    public static long getDayCount(Date start_date) {
        return start_date.getTime() / Constant.DAY_MILLISSECOND;
    }

    //date转到1790天数
    public static Date addDate(Date date, int days) {
        return new Date(date.getTime() + days * Constant.DAY_MILLISSECOND);
    }


    private com.haibin.calendarview.Calendar getSchemeCalendar(int year, int month, int day, int color, String text) {
        com.haibin.calendarview.Calendar calendar = new com.haibin.calendarview.Calendar();
        calendar.setYear(year);
        calendar.setMonth(month);
        calendar.setDay(day);
        calendar.setSchemeColor(color);//如果单独标记颜色、则会使用这个颜色
        calendar.setScheme(text);
        return calendar;
    }
}
